package org.example.core.util;

import org.springframework.core.NamedThreadLocal;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import java.util.Objects;

public class TransactionUtils {

    private static final ThreadLocal<TransactionStatus> transactionStatus =
            new NamedThreadLocal<>("transaction status");

    public static void begin(
            PlatformTransactionManager transactionManager,
            Transactional annotation
    ) {
        Objects.requireNonNull(transactionManager);
        Objects.requireNonNull(annotation);

        DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
        definition.setIsolationLevel(annotation.isolation().value());
        definition.setPropagationBehavior(annotation.propagation().value());
        definition.setReadOnly(annotation.readOnly());
        definition.setTimeout(annotation.timeout());

        TransactionStatus status = transactionManager.getTransaction(definition);
        transactionStatus.set(status);
    }

    public static void commit(PlatformTransactionManager transactionManager) {
        TransactionStatus status = transactionStatus.get();
        if (status != null) {
            transactionManager.commit(status);
            transactionStatus.remove();
        }
    }

    public static void rollback(PlatformTransactionManager transactionManager) {
        TransactionStatus status = transactionStatus.get();
        if (status != null) {
            transactionManager.rollback(status);
            transactionStatus.remove();
        }
    }

}
